package com.gym.core.httpclient;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gym.core.spring.SpringUtil;

/**
 * http请求工具类
 * 
 * 1、HttpClient3.x官方已经不再支持功能更新. 官方建议使用HttpClient4.x版本.
 * 2、DefaultHttpClient 为线程安全的实例,不必每次请求都创建.
 * 3、对于请求并发较高的情况，使用连接池 复用连接 比HttpClient3.x 有更好的性能
 * @author xinchun.wang 2014-11-13 下午9:45:20
 */
@SuppressWarnings("deprecation")
public class HttpClientUtil {
	private  static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
	private  static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
	private  static final String ENCODING_GZIP = "gzip";
	private HttpClient httpclient;
	private int connTimeoutMinis;
	private int readTimeoutMinis;
	private static final int times = 2;
	
	private static final String contentEncoding = "UTF-8";
	
	private static HttpClientUtil instance;
	public static HttpClientUtil getInstance() {
		if(instance == null){
			instance = SpringUtil.getCtx().getBean(HttpClientUtil.class);
		}
		return instance;
	}
	
	
	public  String postData(String url, List<NameValuePair> nameValuePairs){
		return postData(url,nameValuePairs,connTimeoutMinis,readTimeoutMinis,contentEncoding);
	}
	
	public  String postData(String url, List<NameValuePair> nameValuePairs,String contentEncoding){
		return postData(url,nameValuePairs,connTimeoutMinis,readTimeoutMinis,contentEncoding);
	}
	
	public  String postData(String url, List<NameValuePair> nameValuePairs,int connTimeoutMinis,int readTimeoutMinis,String contentEncoding) {
		return postData(url, nameValuePairs, null,connTimeoutMinis,readTimeoutMinis,contentEncoding);
	}
	
	/**
	 * 通过post提交方式获取url指定的资源和数据*/
	public  String postData(String url,List<NameValuePair> nameValuePairs, Map<String, String> headers,int connTimeoutMinis,int readTimeoutMinis,String contentEncoding) {
		HttpPost httpPost = new HttpPost(url);
		try {
			if (headers != null && headers.size() > 0) {
				Set<Map.Entry<String, String>> set = headers.entrySet();
				for (Iterator<Map.Entry<String, String>> it = set.iterator(); it.hasNext();) {
					Map.Entry<String, String> header = it.next();
					if (header != null) {
						httpPost.setHeader(header.getKey(), header.getValue());
					}
				}
			}
			if (nameValuePairs != null && nameValuePairs.size() > 0) {
				httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));
			}
			
			if(connTimeoutMinis > 0 &&  readTimeoutMinis >0){
				httpPost.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connTimeoutMinis);
				httpPost.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, readTimeoutMinis);
			}
			
			HttpResponse response = httpclient.execute(httpPost);
			if(response.getStatusLine().getStatusCode() != 200){
				//TODO
			}
			HttpEntity entity = response.getEntity();
			String info = EntityUtils.toString(entity, contentEncoding);
			return info;
		} catch (Exception e) {
			logger.error("postData Exception url: {}", url, e);
		} finally {
			httpPost.releaseConnection();
		}
		return "";
	}
	
	
	public  String getData(String url) {
		return getData(url,times,contentEncoding);
	}
	
	public  String getData(String url,String contentEncoding) {
		return getData(url,times,contentEncoding);
	}
	
	
	public  String getData(String url,int times,String contentEncoding) {
		return getData(url,connTimeoutMinis,readTimeoutMinis,times,contentEncoding);
	}
	/**
	 * 通过get方法获取url资源的数据
	 * @param url 服务器地址
	 * @return 返回响应的文本，如果请求发生异常
	 */
	public  String getData(String url,int connTimeoutMinis,int readTimeoutMinis,int times,String contentEncoding) {
		return getData(url,null,connTimeoutMinis,readTimeoutMinis,times,contentEncoding);
	}
	
	
	public  String getData(String url, Map<String, String> headers,int connTimeoutMinis,int readTimeoutMinis,int times,String contentEncoding){
		for(int i = 0;i<times;i++){
			String result =  getData(url, null,connTimeoutMinis,readTimeoutMinis,contentEncoding);
			if(StringUtils.isNotEmpty(result)){
				return result;
			}
		}
		return "";
	}
	/**
	 * 带header的get请求
	 * 
	 * @param url 服务器地址
	 * @param headers  添加的请求header信息
	 * @return 返回服务器响应的文本，出错抛出DajieHttpRequestException异常
	 */
	public  String getData(String url, Map<String, String> headers,int connTimeoutMinis,int readTimeoutMinis,String contentEncoding) {
		HttpGet httpGet = new HttpGet(url);
		if (headers != null && headers.size() > 0) {
			Set<Map.Entry<String, String>> set = headers.entrySet();
			for (Iterator<Map.Entry<String, String>> it = set.iterator(); it.hasNext();) {
				Map.Entry<String, String> header = it.next();
				if (header != null) {
					httpGet.setHeader(header.getKey(), header.getValue());
				}
			}
		}
		if(connTimeoutMinis > 0 &&  readTimeoutMinis >0){
			httpGet.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connTimeoutMinis);
			httpGet.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, readTimeoutMinis);
		}
		try {
			HttpResponse response =  httpclient.execute(httpGet);
			if(response.getStatusLine().getStatusCode() != 200){
				//TODO
			}
			HttpEntity entity = response.getEntity();
			String info = EntityUtils.toString(entity, contentEncoding);
			return info;
		} catch (Exception e) {
			logger.error("getData Exception url: {}", url, e);
		} finally {
			httpGet.releaseConnection();
		}
		return "";
	}



	public  byte[] getByteData(String url) {
		return getByteData(url,connTimeoutMinis,readTimeoutMinis,times);
	}
	/**
	 * 通过get方法获取url资源的数据
	 * @param url 服务器地址
	 * @return 返回响应的文本，如果请求发生异常
	 */
	public  byte[] getByteData(String url,int connTimeoutMinis,int readTimeoutMinis,int times) {
		return getByteData(url, null,connTimeoutMinis,readTimeoutMinis,times);
	}
	
	public  byte[] getByteData(String url, Map<String, String> headers,int connTimeoutMinis,int readTimeoutMinis,int times){
		for(int i = 0;i<times;i++){
			byte[] result =  getByteData(url, null,connTimeoutMinis,readTimeoutMinis);
			if(result == null || result.length == 0){
				continue;
			}
			return result;
		}
		return new byte[0];
	
	}
	
	/**
	 * 带header的get请求
	 * 
	 * @param url 服务器地址
	 * @param headers  添加的请求header信息
	 * @return 返回服务器响应的文本，出错抛出DajieHttpRequestException异常
	 */
	public  byte[] getByteData(String url, Map<String, String> headers,int connTimeoutMinis,int readTimeoutMinis) {
		HttpGet httpGet = new HttpGet(url);
		if (headers != null && headers.size() > 0) {
			Set<Map.Entry<String, String>> set = headers.entrySet();
			for (Iterator<Map.Entry<String, String>> it = set.iterator(); it.hasNext();) {
				Map.Entry<String, String> header = it.next();
				if (header != null) {
					httpGet.setHeader(header.getKey(), header.getValue());
				}
			}
		}
		if(connTimeoutMinis > 0 &&  readTimeoutMinis >0){
			httpGet.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connTimeoutMinis);
			httpGet.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, readTimeoutMinis);
		}
		try {
			HttpResponse response =  httpclient.execute(httpGet);
			if(response.getStatusLine().getStatusCode() != 200){
				//TODO
			}
			HttpEntity entity = response.getEntity();
			byte[] info = EntityUtils.toByteArray(entity);
			return info;
		} catch (Exception e) {
			logger.error("getData Exception url: {}", url, e);
		} finally {
			httpGet.releaseConnection();
		}
		return new byte[0];
	}
	
	
	
	
	/**
	 * 对httpclient 做压缩处理和解压缩处理 */
	public void initClient() {
		httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connTimeoutMinis);
		httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, readTimeoutMinis);
		((DefaultHttpClient)httpclient).addRequestInterceptor(new HttpRequestInterceptor() {
			@Override
			public void process(HttpRequest request, HttpContext context) {
				if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
					request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
				}
			}
		});

		((DefaultHttpClient)httpclient).addResponseInterceptor(new HttpResponseInterceptor() {
			@Override
			public void process(HttpResponse response, HttpContext context) {
				final HttpEntity entity = response.getEntity();
				if(entity == null){
					return;
				}
				final Header encoding = entity.getContentEncoding();
				if (encoding != null) {
					for (HeaderElement element : encoding.getElements()) {
						if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
							response.setEntity(new GzipDecompressingEntity(
									response.getEntity()));
							break;
						}
					}
				}
			}
		});
	}
	
	
	/**
	 * 关闭客户端*/
	public void destroyClient(){
		httpclient.getConnectionManager().shutdown();
	}

	public void setHttpclient(HttpClient httpclient) {
		this.httpclient = httpclient;
	}

	public void setConnTimeoutMinis(int connTimeoutMinis) {
		this.connTimeoutMinis = connTimeoutMinis;
	}

	public void setReadTimeoutMinis(int readTimeoutMinis) {
		this.readTimeoutMinis = readTimeoutMinis;
	}
	
}
